home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 December / MACPOWER-1997-12.ISO.7z / MACPOWER-1997-12.ISO / AMUG / PROGRAMMING / Raven 1.2.sit / Raven 1.2 / Source / Foundation / OS / ZResUtils.cpp < prev    next >
Text File  |  1997-08-07  |  17KB  |  727 lines

  1. /*
  2.  *  File:       ZResUtils.cpp
  3.  *  Summary:    Resource manager utilities.
  4.  *  Written by: Jesse Jones
  5.  *
  6.  *  Copyright ゥ 1996-1997 Jesse Jones. 
  7.  *    For conditions of distribution and use, see copyright notice in ZTypes.h  
  8.  *
  9.  *  Change History (most recent first):
  10.  *
  11.  *         <2>     4/12/97    JDJ        Added GetResourceInfo.
  12.  *         <1>     2/03/96    JDJ        Created
  13.  */
  14.  
  15. #include <ZResUtils.h>
  16.  
  17. #include <Errors.h>
  18. #include <LowMem.h>
  19. #include <Resources.h>
  20. #include <Script.h>
  21.  
  22. #include <SLFunctions.h>
  23. #include <ZDebug.h>
  24. #include <ZExceptions.h>
  25. #include <ZStringUtils.h>
  26.  
  27.  
  28. //-----------------------------------
  29. //    Constants
  30. //
  31. const ulong kMaxBufferSize = 4*1024L*1024L;    // Used for sanity checking
  32.  
  33.  
  34. // ===================================================================================
  35. //    Helper Functions
  36. // ===================================================================================
  37.  
  38. //---------------------------------------------------------------
  39. //
  40. // IsPurgeableHand
  41. //
  42. //---------------------------------------------------------------
  43. static bool IsPurgeableHand(Handle hand)
  44. {
  45.     ASSERT(hand != nil);
  46.     
  47.     char state = HGetState(hand);
  48.     OSErr err = MemError();
  49.     
  50.     if (err == noErr)
  51.         return (state & 0x40) != 0;
  52.     else if (err == nilHandleErr)
  53.         return true;                                // Handle has been purged.
  54.     else
  55.         DEBUGSTR("Error %d in IsPurgeable.", err);
  56.         
  57.     return false;
  58. }
  59.  
  60.  
  61. //---------------------------------------------------------------
  62. //
  63. // IsResourceHand
  64. //
  65. //---------------------------------------------------------------
  66. static bool IsResourceHand(Handle hand)
  67. {
  68.     ASSERT(hand != nil);                // Might want to treat this like IsPurgeable.
  69.  
  70.     char state = HGetState(hand);
  71.     ASSERT(MemError() == noErr);
  72.     return (state & 0x20) != 0;
  73. }
  74.  
  75.  
  76. //---------------------------------------------------------------
  77. //
  78. // GetResourceNoLoad (ResType, ResID, bool)
  79. //
  80. //---------------------------------------------------------------
  81. static Handle GetResourceNoLoad(ResType type, ResID id, bool get1)
  82. {
  83.     Handle rsrc = nil;
  84.     
  85.     SetResLoad(false);
  86.     if (get1)
  87.         rsrc = Get1Resource(type, id);
  88.     else
  89.         rsrc = GetResource(type, id);
  90.     OSErr err = ResError();
  91.     SetResLoad(true);
  92.     
  93.     return rsrc;
  94. }
  95.  
  96.  
  97. //---------------------------------------------------------------
  98. //
  99. // GetResourceNoLoad (ResType, string, bool)
  100. //
  101. //---------------------------------------------------------------
  102. static Handle GetResourceNoLoad(ResType type, const string& inName, bool get1)
  103. {
  104.     Handle rsrc = nil;
  105.     
  106.     unsigned char* name = StrToPStr(inName);        
  107.     
  108.     SetResLoad(false);
  109.     if (get1)
  110.         rsrc = Get1NamedResource(type, name);
  111.     else
  112.         rsrc = GetNamedResource(type, name);
  113.     OSErr err = ResError();
  114.     SetResLoad(true);
  115.     
  116.     return rsrc;
  117. }
  118.  
  119.  
  120. //---------------------------------------------------------------
  121. //
  122. // CreateResource
  123. //
  124. // Creates a resource of the specified size or resizes an existing
  125. // resource.
  126. //
  127. //---------------------------------------------------------------
  128. static Handle CreateResource(ResType type, ResID id, const string& name, ulong size, short attrs)
  129. {
  130.     Handle handle = nil;
  131.     OSErr err = noErr;
  132.  
  133.     SLDisable();                    // Spotlight complains if the resource doesn't exist
  134.     if (name.length() > 0)
  135.         handle = Get1NamedResource(type, StrToPStr(name));
  136.     else
  137.         handle = Get1Resource(type, id);
  138.     SLEnable();
  139.  
  140.     if (handle == nil) {
  141.         handle = NewHandle(size);
  142.         ThrowIfMemFail(handle);
  143.         
  144.         if (name.length() > 0)
  145.             id = UniqueID(type);
  146.         
  147.         AddResource(handle, type, id, StrToPStr(name));
  148.         err = ResError();
  149.         if (err == noErr) {
  150.             if (attrs != 0)
  151.                 SetResAttrs(handle, (short) (attrs | resChanged));        // preserve resChanged (it is set by AddResource())
  152.         
  153.         } else {
  154.             DisposeHandle(handle);
  155.             ThrowIfOSErr(err);
  156.         }
  157.                     
  158.     } else if (GetHandleSize(handle) != size) {
  159.         SetHandleSize(handle, size);
  160.         err = MemError();
  161.         if (err == noErr) {
  162.             ChangedResource(handle);
  163.             err = ResError();
  164.             
  165.             if (err != noErr) {
  166.                 ReleaseIfResource(handle);
  167.                 ThrowIfOSErr(err);
  168.             }
  169.         }
  170.         
  171.     } else {
  172.         ChangedResource(handle);                        // Make sure resChanged bit is set.
  173.         ThrowIfResError();
  174.     }
  175.  
  176.     return handle;
  177. }
  178.  
  179. #pragma mark -
  180.  
  181. // ===================================================================================
  182. //    Global Functions
  183. // ===================================================================================
  184.  
  185. //---------------------------------------------------------------
  186. //
  187. // ReadResource (ResType, ResID, void*, ulong)
  188. //
  189. //---------------------------------------------------------------
  190. void ReadResource(ResType type, ResID id, void* buffer, ulong bytes)
  191. {    
  192.     ASSERT(buffer != nil);
  193.     ASSERT(bytes < kMaxBufferSize);
  194.     
  195.     Handle rsrc = GetResourceNoLoad(type, id, false);
  196.     ThrowIfResFail(rsrc);
  197.     
  198.     long handleSize = GetResourceSizeOnDisk(rsrc);
  199.     ASSERT(ResError() == noErr && handleSize >= bytes);
  200.  
  201.     ReadPartialResource(rsrc, 0, buffer, (long) bytes);
  202.     OSErr err = ResError();
  203.  
  204.     ReleaseResource(rsrc);
  205.  
  206.     ThrowIfOSErr(err);
  207. }
  208.  
  209.  
  210. //---------------------------------------------------------------
  211. //
  212. // ReadResource (ResType, string, void*, ulong)
  213. //
  214. //---------------------------------------------------------------
  215. void ReadResource(ResType type, const string& name, void* buffer, ulong bytes)
  216. {
  217.     ASSERT(buffer != nil);
  218.     ASSERT(bytes < kMaxBufferSize);
  219.     
  220.     Handle rsrc = GetResourceNoLoad(type, name, false);
  221.     ThrowIfResFail(rsrc);
  222.     
  223.     long handleSize = GetResourceSizeOnDisk(rsrc);
  224.     ASSERT(ResError() == noErr && handleSize >= bytes);
  225.  
  226.     ReadPartialResource(rsrc, 0, buffer, (long) bytes);
  227.     OSErr err = ResError();
  228.  
  229.     ReleaseResource(rsrc);
  230.  
  231.     ThrowIfOSErr(err);
  232. }
  233.  
  234.  
  235. //---------------------------------------------------------------
  236. //
  237. // Read1Resource (ResType, ResID, void*, ulong)
  238. //
  239. //---------------------------------------------------------------
  240. void Read1Resource(ResType type, ResID id, void* buffer, ulong bytes)
  241. {
  242.     ASSERT(buffer != nil);
  243.     ASSERT(bytes < kMaxBufferSize);
  244.     
  245.     Handle rsrc = GetResourceNoLoad(type, id, true);
  246.     ThrowIfResFail(rsrc);
  247.     
  248.     long handleSize = GetResourceSizeOnDisk(rsrc);
  249.     ASSERT(ResError() == noErr && handleSize >= bytes);
  250.  
  251.     ReadPartialResource(rsrc, 0, buffer, (long) bytes);
  252.     OSErr err = ResError();
  253.  
  254.     ReleaseResource(rsrc);
  255.  
  256.     ThrowIfOSErr(err);
  257. }
  258.  
  259.  
  260. //---------------------------------------------------------------
  261. //
  262. // Read1Resource (ResType, string, void*, ulong)
  263. //
  264. //---------------------------------------------------------------
  265. void Read1Resource(ResType type, const string& name, void* buffer, ulong bytes)
  266. {
  267.     ASSERT(buffer != nil);
  268.     ASSERT(bytes < kMaxBufferSize);
  269.     
  270.     Handle rsrc = GetResourceNoLoad(type, name, true);
  271.     ThrowIfResFail(rsrc);
  272.     
  273.     long handleSize = GetResourceSizeOnDisk(rsrc);
  274.     ASSERT(ResError() == noErr && handleSize >= bytes);
  275.  
  276.     ReadPartialResource(rsrc, 0, buffer, (long) bytes);
  277.     OSErr err = ResError();
  278.  
  279.     ReleaseResource(rsrc);
  280.  
  281.     ThrowIfOSErr(err);
  282. }
  283.  
  284.  
  285. //---------------------------------------------------------------
  286. //
  287. // WriteResource (ResType, ResID, Handle, bool)
  288. //
  289. //---------------------------------------------------------------
  290. void WriteResource(ResType type, ResID id, Handle data, bool purgeable)
  291. {
  292.     ASSERT(data != nil && *data != nil);
  293.     ASSERT(!IsPurgeableHand(data));
  294.     
  295.     short attrs = 0;
  296.     if (purgeable)
  297.         attrs += resPurgeable;
  298.  
  299.     ulong size = (ulong) GetHandleSize(data);
  300.     Handle rsrc = CreateResource(type, id, "", size, attrs);
  301.  
  302.     BlockMoveData(*data, *rsrc, size);
  303.     WriteResource(rsrc);
  304.     ThrowIfResError();
  305.  
  306.     ReleaseIfResource(rsrc);
  307. }
  308.  
  309.  
  310. //---------------------------------------------------------------
  311. //
  312. // WriteResource (ResType, string, Handle, bool)
  313. //
  314. //---------------------------------------------------------------
  315. void WriteResource(ResType type, const string& name, Handle data, bool purgeable)
  316. {
  317.     ASSERT(data != nil && *data != nil);
  318.     ASSERT(!IsPurgeableHand(data));
  319.     
  320.     short attrs = 0;
  321.     if (purgeable)
  322.         attrs += resPurgeable;
  323.  
  324.     ulong size = (ulong) GetHandleSize(data);
  325.     Handle rsrc = CreateResource(type, 0, name, size, attrs);
  326.  
  327.     BlockMoveData(*data, *rsrc, size);
  328.     WriteResource(rsrc);
  329.     ThrowIfResError();
  330.  
  331.     ReleaseIfResource(rsrc);
  332. }
  333.  
  334.  
  335. //---------------------------------------------------------------
  336. //
  337. // WriteResource (ResType, ResID, const void*, ulong, bool)
  338. //
  339. //---------------------------------------------------------------
  340. void WriteResource(ResType type, ResID id, const void* buffer, ulong bytes, bool purgeable)
  341. {
  342.     ASSERT(buffer != nil);
  343.     ASSERT(bytes < kMaxBufferSize);
  344.     
  345.     short attrs = 0;
  346.     if (purgeable)
  347.         attrs += resPurgeable;
  348.  
  349.     Handle rsrc = CreateResource(type, id, "", bytes, attrs);
  350.  
  351.     BlockMoveData(buffer, *rsrc, bytes);
  352.     WriteResource(rsrc);
  353.     ThrowIfResError();
  354.  
  355.     ReleaseIfResource(rsrc);
  356. }
  357.  
  358.  
  359. //---------------------------------------------------------------
  360. //
  361. // WriteResource (ResType, string, const void*, ulong, bool)
  362. //
  363. //---------------------------------------------------------------
  364. void WriteResource(ResType type, const string& name, const void* buffer, ulong bytes, bool purgeable)
  365. {
  366.     ASSERT(buffer != nil);
  367.     ASSERT(bytes < kMaxBufferSize);
  368.     
  369.     short attrs = 0;
  370.     if (purgeable)
  371.         attrs += resPurgeable;
  372.  
  373.     Handle rsrc = CreateResource(type, 0, name, bytes, attrs);
  374.  
  375.     BlockMoveData(buffer, *rsrc, bytes);
  376.     WriteResource(rsrc);
  377.     ThrowIfResError();
  378.  
  379.     ReleaseIfResource(rsrc);
  380. }
  381.  
  382.  
  383. //---------------------------------------------------------------
  384. //
  385. // Delete1Resource (ResType)
  386. //
  387. //---------------------------------------------------------------
  388. void Delete1Resource(ResType type)
  389. {
  390.     short num = ::Count1Resources(type);
  391.     for (short index = 1; index <= num; index++) {
  392.         Handle hand;
  393.         
  394.         {
  395.         TNoResLoad noLoad;
  396.             hand = ::Get1IndResource(type, 1);
  397.             ThrowIfResFail(hand);
  398.         }
  399.         
  400.         ::RemoveResource(hand);
  401.         ThrowIfResError();
  402.         
  403.         ::DisposeHandle(hand);
  404.     }
  405. }
  406.  
  407.  
  408. //---------------------------------------------------------------
  409. //
  410. // DeleteResource (ResType)
  411. //
  412. //---------------------------------------------------------------
  413. void DeleteResource(ResType type)
  414. {
  415.     short num = ::CountResources(type);
  416.     for (short index = 1; index <= num; index++) {
  417.         Handle hand;
  418.         
  419.         {
  420.         TNoResLoad noLoad;
  421.             hand = ::GetIndResource(type, 1);
  422.             ThrowIfResFail(hand);
  423.         }
  424.         
  425.         ::RemoveResource(hand);
  426.         ThrowIfResError();
  427.         
  428.         ::DisposeHandle(hand);
  429.     }
  430. }
  431.  
  432.  
  433. //---------------------------------------------------------------
  434. //
  435. // DeleteResource (ResType, ResID)
  436. //
  437. //---------------------------------------------------------------
  438. void DeleteResource(ResType type, ResID id)
  439. {
  440.     Handle handle = GetResourceNoLoad(type, id, true);
  441.     ASSERT(handle != nil);
  442.  
  443.     if (handle != nil) {
  444.         short refNum = HomeResFile(handle);
  445.         RemoveResource(handle);
  446.         ThrowIfResError();
  447.         if (refNum != -1)
  448.             UpdateResFile(refNum);
  449.         DisposeHandle(handle);
  450.     }
  451. }
  452.  
  453.  
  454. //---------------------------------------------------------------
  455. //
  456. // DeleteResource (ResType, string)
  457. //
  458. //---------------------------------------------------------------
  459. void DeleteResource(ResType type, const string& name)
  460. {
  461.     Handle handle = GetResourceNoLoad(type, name, true);
  462.     ASSERT(handle != nil);
  463.  
  464.     if (handle != nil) {
  465.         short refNum = HomeResFile(handle);
  466.         RemoveResource(handle);
  467.         ThrowIfResError();
  468.         if (refNum != -1)
  469.             UpdateResFile(refNum);
  470.         DisposeHandle(handle);
  471.     }
  472. }
  473.  
  474.  
  475. //---------------------------------------------------------------
  476. //
  477. // Has1Resource (ResType, ResID)
  478. //
  479. //---------------------------------------------------------------
  480. bool Has1Resource(ResType type, ResID id)
  481. {
  482.     SLDisable();
  483.     Handle rsrc = GetResourceNoLoad(type, id, true);
  484.     
  485.     bool has = rsrc != nil;
  486.     
  487.     ReleaseResource(rsrc);
  488.     SLEnable();
  489.     
  490.     return has;
  491. }
  492.  
  493.  
  494. //---------------------------------------------------------------
  495. //
  496. // Has1Resource (ResType, string)
  497. //
  498. //---------------------------------------------------------------
  499. bool Has1Resource(ResType type, const string& name)
  500. {
  501.     SLDisable();
  502.     Handle rsrc = GetResourceNoLoad(type, name, true);
  503.     
  504.     bool has = rsrc != nil;
  505.     
  506.     ReleaseResource(rsrc);                
  507.     SLEnable();
  508.     
  509.     return has;
  510. }
  511.  
  512.  
  513. //---------------------------------------------------------------
  514. //
  515. // HasResource (ResType, ResID)
  516. //
  517. //---------------------------------------------------------------
  518. bool HasResource(ResType type, ResID id)
  519. {
  520.     SLDisable();
  521.     Handle rsrc = GetResourceNoLoad(type, id, false);
  522.     
  523.     bool has = rsrc != nil;
  524.     
  525.     ReleaseResource(rsrc);                
  526.     SLEnable();
  527.     
  528.     return has;
  529. }
  530.  
  531.  
  532. //---------------------------------------------------------------
  533. //
  534. // HasResource (ResType, string)
  535. //
  536. //---------------------------------------------------------------
  537. bool HasResource(ResType type, const string& name)
  538. {
  539.     SLDisable();
  540.     Handle rsrc = GetResourceNoLoad(type, name, false);
  541.     
  542.     bool has = rsrc != nil;
  543.     
  544.     ReleaseResource(rsrc);                
  545.     SLEnable();
  546.     
  547.     return has;
  548. }
  549.  
  550.  
  551. //---------------------------------------------------------------
  552. //
  553. // ChangeResourceName
  554. //
  555. //---------------------------------------------------------------
  556. void ChangeResourceName(Handle handle, const string& name)
  557. {
  558.     short    id;
  559.     ResType    type;
  560.     Str255    currentName;
  561.  
  562.     GetResInfo(handle, &id, &type, currentName);
  563.     ThrowIfResError();
  564.  
  565.     if (name != PStrToStr(currentName)) {
  566.         SetResInfo(handle, id, StrToPStr(name));
  567.         ThrowIfResError();
  568.     }
  569. }
  570.  
  571.  
  572. //---------------------------------------------------------------
  573. //
  574. // ReleaseIfResource
  575. //
  576. //---------------------------------------------------------------
  577. Handle ReleaseIfResource(Handle handle)
  578. {
  579.     if (handle != nil) {
  580.         ASSERT(IsResourceHand(handle));
  581.         ReleaseResource(handle);
  582.     }
  583.  
  584.     return nil;
  585. }
  586.  
  587.  
  588. //---------------------------------------------------------------
  589. //
  590. // GetResourceInfo
  591. //
  592. //---------------------------------------------------------------
  593. SResourceInfo GetResourceInfo(Handle hand)
  594. {
  595.     short    id;
  596.     ResType    type;
  597.     Str255    name;
  598.  
  599.     GetResInfo(hand, &id, &type, name);
  600.     ThrowIfResError();
  601.     
  602.     return SResourceInfo(type, id, PStrToStr(name));
  603. }
  604.  
  605. #pragma mark -
  606.  
  607. // ===================================================================================
  608. //    class TOpenResFile
  609. // ===================================================================================
  610.  
  611. //---------------------------------------------------------------
  612. //
  613. // TOpenResFile::~TOpenResFile
  614. //
  615. //---------------------------------------------------------------
  616. TOpenResFile::~TOpenResFile()
  617. {
  618.     if (mRefNum != -1 && mRefNum != 0)         // zero closes all open resource files!
  619.         CloseResFile(mRefNum);
  620. }
  621.  
  622.         
  623. //---------------------------------------------------------------
  624. //
  625. // TOpenResFile::TOpenResFile
  626. //
  627. //---------------------------------------------------------------
  628. TOpenResFile::TOpenResFile(const FSSpec& spec, SignedByte permission)
  629. {
  630.     SLDisable();
  631.     mRefNum = FSpOpenResFile(&spec, permission);
  632.     OSErr err = ResError();
  633.     SLEnable();
  634.     
  635.     if (err == eofErr) {
  636.         FInfo info;        
  637.         OSErr err = HGetFInfo(spec.vRefNum, spec.parID, spec.name, &info);
  638.         ThrowIfOSErr(err);
  639.         
  640.         FSpCreateResFile(&spec, info.fdCreator, info.fdType, smSystemScript);
  641.         ThrowIfResError();
  642.  
  643.         mRefNum = FSpOpenResFile(&spec, permission);
  644.         ThrowIfResError();
  645.         
  646.     } else
  647.         ThrowIfOSErr(err);
  648. }
  649.  
  650. #pragma mark -
  651.  
  652. // ===================================================================================
  653. //    class TSaveResFile
  654. // ===================================================================================
  655.  
  656. //---------------------------------------------------------------
  657. //
  658. // TSaveResFile::~TSaveResFile
  659. //
  660. //---------------------------------------------------------------
  661. #pragma segment ZTools
  662. TSaveResFile::~TSaveResFile()
  663. {
  664.     UseResFile(mSavedResFile);
  665. }
  666.  
  667.     
  668. //---------------------------------------------------------------
  669. //
  670. // TSaveResFile::TSaveResFile ()
  671. //
  672. //---------------------------------------------------------------
  673. #pragma segment ZTools
  674. TSaveResFile::TSaveResFile()
  675. {
  676.     mSavedResFile = CurResFile();
  677. }
  678.  
  679.  
  680. //---------------------------------------------------------------
  681. //
  682. // TSaveResFile::TSaveResFile (short)
  683. //
  684. //---------------------------------------------------------------
  685. TSaveResFile::TSaveResFile(short newResFile)
  686. {
  687.     mSavedResFile = CurResFile();
  688.  
  689.     if (newResFile != kNoFileRefNum) {
  690.         UseResFile(newResFile);
  691.         ThrowIfResError();
  692.     }
  693. }
  694.  
  695. #pragma mark -
  696.  
  697. // ===================================================================================
  698. //    class TNoResLoad
  699. // ===================================================================================
  700.  
  701. //---------------------------------------------------------------
  702. //
  703. // TNoResLoad::~TNoResLoad
  704. //
  705. //---------------------------------------------------------------
  706. TNoResLoad::~TNoResLoad()
  707. {
  708.     if (mDisabled) 
  709.         SetResLoad(true);
  710. }
  711.  
  712.     
  713. //---------------------------------------------------------------
  714. //
  715. // TNoResLoad::TNoResLoad
  716. //
  717. //---------------------------------------------------------------
  718. TNoResLoad::TNoResLoad()
  719. {
  720.     mDisabled = LMGetResLoad() != 0; 
  721.     
  722.     if (mDisabled) 
  723.         SetResLoad(false);
  724. }
  725.  
  726.  
  727.